Python 数据可视化:第16章-下载数据
1 分析CSV 文件
章将从网上下载数据,并对其进行可视化。网上的数据多得令人难以置信,大多未经仔细检查。如果能够对这些数据进行分析,就能发现别人没有发现的规律和关联。
1.1 分析CSV 文件头
这是阿拉斯加州锡特卡2018年1月1日的天气数据,其中包含当天的最高温度和最低温度,还有众多其他的数据。CSV文件对人来说阅读起来比较麻烦,但程序可轻松提取并处理其中的值,有助于加快数据分析过程
sitka_highs.py
import csv
filename = 'data/sitka_weather_2018_simple.csv'
with open(filename) as file_object:
# 使用csv.reader 阅读器读取csv 文件。并入内存。
reader = csv.reader(file_object)
# 模块csv 包含函数next(),
# next() 函数返回文件中的下一行。
header_row = next(reader)
print(header_row)
- reader 处理文件中以逗号分隔的第一行数据,并将每项数据都作为一个元素存储在列表中。
- 普通read() 函数只是把
1.1.1 数据说明
[[#给图表区域着色]]
['STATION', 'NAME', 'DATE', 'PRCP', 'TAVG', 'TMAX', 'TMIN']
| 字段 | 说明 |
|---|---|
| STATION | 表示记录数据的气象站编码 |
| NAME | 表示记录数据的气象站名称 |
| DATE | 日期 |
| TAVG | 平均温度 |
| TMAX | 最高温度 |
| TMIN | 最低温度 |
注意:reader_doc = file_object.read()
此代码是把文件内容读入变量中,不经过CSV 处理,所以是整块文本。
1.1.2 打印文件头及其位置
import csv
filename = 'data/sitka_weather_2018_simple.csv'
with open(filename) as file_object:
reader = csv.reader(file_object)
header_row = next(reader)
#
for index, column_header in enumerate(header_row):
print(index, column_header)
| 函数 | 说明 |
|---|---|
| enumerate | 获取每个元素的索引和其包含的值。 |
1.2 提取并读取数据
知道需要哪些列中的数据后,我们来读取一些数据。首先,读取每天的最高温度
import csv
filename = 'data/sitka_weather_2018_simple.csv'
with open(filename) as file_object:
reader = csv.reader(file_object)
header_row = next(reader)
for index, column_header in enumerate(header_row):
print(index, column_header)
highs = []
for row in reader:
high = int(row[5])
highs.append(high)
print(highs)
1.2.1 绘制温度图表
import csv
import matplotlib.pyplot as plt
filename = 'data/sitka_weather_2018_simple.csv'
with open(filename) as file_object:
reader = csv.reader(file_object)
header_row = next(reader)
for index, column_header in enumerate(header_row):
print(index, column_header)
highs = []
for row in reader:
high = int(row[5])
highs.append(high)
print(highs)
# 根据最高温度绘制图形。
plt.style.use('seaborn')
#设置字体 ,如果不设置字体,则汉字无法显示
plt.rcParams["font.sans-serif"]=["SimHei"]
#该语句解决图像中的“-”负号的乱码问题
plt.rcParams["axes.unicode_minus"]=False
fig, ax = plt.subplots()
ax.plot(highs, c='red')
# 设置图形的格式。
ax.set_title("2018年7年每日最高温度,", fontsize=24)
ax.set_xlabel('', fontsize=16)
ax.tick_params(axis='both', which='major', labelsize=16)
plt.show()
1.2.2 plot() 函数参考
matplotlib.pyplot.plot — Matplotlib 3.6.0 documentation
1.2.3 模块datetime
from datetime import datetime
first_date =datetime.strptime('2018-07-01', '%Y-%m-%d')
print(first_date)
- 首先导入模块datetime 中的datetime 类
- 调用方法strptime() ,并将包含所需日期的字符串作为第一个实参。
- 第二个实参告诉Python如何设置日期的格式。在这里,'%Y-' 让Python将字符串中第一个连字符前面的部分视为四位的年份,'%m-' 让Python将第二个连字符前面的部分视为表示月份的数,'%d' 让Python将字符串的最后一部分视为月份中的一天(1~31)。
1.2.4 表16-1 模块datetime 中设置日期和时间格式的实参
| 实参 | 含义 |
|---|---|
| %A | 星期几,如Monday |
| %B | 月份名,如January |
| %m | 用数字表示的月份(01~12) |
| %d | 用数字表示月份中的一天(01~31) |
| %Y | 四位数字的年份,如2019 |
| %y | 两位的年份,如19 |
| %H | 24小时制的小时数(00~23) |
| %I | 12小时制的小时数(01~22) |
| %p | am或pm |
| %M | 分钟数(00~59) |
1.2.5 在图表中添加日期
import csv
import matplotlib.pyplot as plt
from datetime import datetime
filename = 'data/sitka_weather_2018_simple.csv'
with open(filename) as file_object:
reader = csv.reader(file_object)
header_row = next(reader)
for index, column_header in enumerate(header_row):
print(index, column_header)
dates,highs = [], []
for row in reader:
current_date = datetime.strptime(row[2], '%Y-%m-%d')
dates.append(current_date)
# ℉ 转换为 摄氏度(℃)
high = (int(row[5]) - 31) // 1.8
highs.append(high)
print(highs)
# 根据最高温度绘制图形。
plt.style.use('seaborn')
#设置字体 ,如果不设置字体,则汉字无法显示
plt.rcParams["font.sans-serif"]=["SimHei"]
#该语句解决图像中的“-”负号的乱码问题
plt.rcParams["axes.unicode_minus"]=False
fig, ax = plt.subplots()
ax.plot(dates,highs, c='red')
# 设置图形的格式。
ax.set_title("2018年7年每日最高温度,", fontsize=24)
ax.set_xlabel("日期", fontsize=16)
ax.set_ylabel("温度(C)", fontsize=16)
fig.autofmt_xdate()
ax.tick_params(axis='both', which='major', labelsize=16)
plt.show()
1.2.6 在同一个figure 中绘制多个数据系列
import csv
import matplotlib.pyplot as plt
from datetime import datetime
filename = 'data/sitka_weather_2018_simple.csv'
with open(filename) as file_object:
reader = csv.reader(file_object)
header_row = next(reader)
for index, column_header in enumerate(header_row):
print(index, column_header)
dates, highs, lows = [], [], []
for row in reader:
#
low = (int(row[6]) -31 ) // 1.8
lows.append(low)
#
current_date = datetime.strptime(row[2], '%Y-%m-%d')
dates.append(current_date)
# ℉ 转换为 摄氏度(℃)
high = (int(row[5]) - 31) // 1.8
highs.append(high)
#
print(highs)
# 根据最高温度绘制图形。
plt.style.use('seaborn')
#设置字体 ,如果不设置字体,则汉字无法显示
plt.rcParams["font.sans-serif"]=["SimHei"]
#该语句解决图像中的“-”负号的乱码问题
plt.rcParams["axes.unicode_minus"]=False
fig, ax = plt.subplots()
ax.plot(dates,highs, c='red')
ax.plot(dates,lows, c='blue')
# 设置图形的格式。
ax.set_title("2018年7年每日最高温度,", fontsize=24)
ax.set_xlabel("日期", fontsize=16)
ax.set_ylabel("温度(C)", fontsize=16)
fig.autofmt_xdate()
ax.tick_params(axis='both', which='major', labelsize=16)
plt.show()
1.3 给图表区域着色
import csv
import matplotlib.pyplot as plt
from datetime import datetime
filename = 'data/sitka_weather_2018_simple.csv'
with open(filename) as file_object:
reader = csv.reader(file_object)
header_row = next(reader)
for index, column_header in enumerate(header_row):
print(index, column_header)
dates, highs, lows = [], [], []
for row in reader:
#
low = (int(row[6]) -31 ) // 1.8
lows.append(low)
#
current_date = datetime.strptime(row[2], '%Y-%m-%d')
dates.append(current_date)
# ℉ 转换为 摄氏度(℃)
high = (int(row[5]) - 31) // 1.8
highs.append(high)
#
print(highs)
# 根据最高温度绘制图形。
plt.style.use('seaborn')
#设置字体 ,如果不设置字体,则汉字无法显示
plt.rcParams["font.sans-serif"]=["SimHei"]
#该语句解决图像中的“-”负号的乱码问题
plt.rcParams["axes.unicode_minus"]=False
fig, ax = plt.subplots()
ax.plot(dates,highs, c='red')
ax.plot(dates,lows, c='blue')
ax.fill_between(dates, highs, lows, facecolor='blue', alpha=0.1)
# 设置图形的格式。
ax.set_title("2018年7年每日最高温度,", fontsize=24)
ax.set_xlabel("日期", fontsize=16)
ax.set_ylabel("温度(C)", fontsize=16)
fig.autofmt_xdate()
ax.tick_params(axis='both', which='major', labelsize=16)
plt.show()
ax.fill_between(dates, highs, lows, facecolor='blue', alpha=0.1)
1.3.1.1 ax.fill_between
| 参数 | 说明 |
|---|---|
| dates | 传入X轴数据 |
| highs | 上边线 |
| lows | 下边线 |
| facecolor | 填充色 |
| alpha | 透明度: 0 表示完全透明, 1 完全不透明 |
1.3.2 错误检查
1.3.3 处理CSV 空值数据。
因为无法将空字符串('')转换为整数。我们只要看一下文件death_valley_2018_simple.csv,就知道缺失了哪项数据,但这里不这样做,而是直接对缺失数据的情形进行处理
import csv
import matplotlib.pyplot as plt
from datetime import datetime
filename = 'data/death_valley_2018_simple.csv'
with open(filename) as file_object:
reader = csv.reader(file_object)
header_row = next(reader)
print(reader)
for index, column_header in enumerate(header_row):
print(index, column_header)
dates, highs, lows = [], [], []
for row in reader:
#
try:
low = (int(row[4]) - 31) // 1.8
high = (int(row[5]) - 31) // 1.8
current_date = datetime.strptime(row[2], '%Y-%m-%d')
except ValueError:
print(f"Missing data for {current_date}")
else:
lows.append(low)
dates.append(current_date)
highs.append(high)
print(highs)
# 根据最高温度绘制图形。
plt.style.use('seaborn')
# 设置字体 ,如果不设置字体,则汉字无法显示
plt.rcParams["font.sans-serif"] = ["SimHei"]
# 该语句解决图像中的“-”负号的乱码问题
plt.rcParams["axes.unicode_minus"] = False
fig, ax = plt.subplots()
ax.plot(dates, highs, c='red')
ax.plot(dates, lows, c='blue')
ax.fill_between(dates, highs, lows, facecolor='blue', alpha=0.1)
# 设置图形的格式。
ax.set_title("2018年7年每日最高温度,", fontsize=24)
ax.set_xlabel("日期", fontsize=16)
ax.set_ylabel("温度(C)", fontsize=16)
fig.autofmt_xdate()
ax.tick_params(axis='both', which='major', labelsize=16)
plt.show()
1.4 天气数据下载
National Centers for Environmental Information (NCEI) (noaa.gov)
- 1) 访问网站NOAA Climate Data Online。在Discover Data By部分,单击SearchTool。在下拉列表Select a Dataset中,选择Daily Summaries。
- 2) 选择一个日期范围,在Search For下拉列表中ZIP Codes,输入你感兴趣地区的邮政编码,再单击Search按钮。
- (3) 在下一个页面中,你将看到指定地区的地图和相关信息。单击地区名下方的View Full Details或单击地图再单击Full Details。
- (4) 向下滚动并单击Station List,以显示该地区的气象站,再选择一个气象站并单击Add to Cart。虽然这个网站使用了购物车图标,但提供的数据是免费的。单击右上角的购物车。
- (5) 在Select the Output中选择Custom GHCN-Daily CSV。确认日期范围无误后单击Continue。
- (6) 在下一个页面中,可选择要下载的数据类型。可以只下载一种数据(如气温),也可以下载该气象站提供的所有数据。做出选择后单击Continue。
- (7) 在最后一个页面,你将看到订单小结。请输入你的电子邮箱地址,再单击Submit Order。你将收到一封确认邮件,指出收到了你的订单。几分钟后,你将收到另一封邮件,其中包含用于下载数据的链接。
- 得到以下文件。
![[chongqing_2018_full.csv]]
![[chongqing_1958_full.csv]] - 分析csv 头信息,获取要绘制的图像信息
import csv
filename = 'data/sitka_weather_2018_full.csv'
with open(filename) as file_object:
reader = csv.reader(file_object)
header_row = next(reader)
first_row = next(reader)
print(first_row)
for index, column_header in enumerate(header_row):
print(index, column_header)
for index, column_header in enumerate(first_row):
print(index, column_header)
- 开始分析重庆历史的最高气温和最低气温
chongqing_highs.py
import csv
import matplotlib.pyplot as plt
from datetime import datetime
filename = 'data/chongqing_2018_full.csv'
with open(filename) as file_object:
reader = csv.reader(file_object)
header_row = next(reader)
print(reader)
for index, column_header in enumerate(header_row):
print(index, column_header)
dates, highs, lows = [], [], []
for row in reader:
try:
low = (int(row[14]) - 31) // 1.8
high = (int(row[12]) - 31) // 1.8
current_date = datetime.strptime(row[5], '%Y-%m-%d')
except ValueError:
print(f"Missing data ")
else:
lows.append(low)
dates.append(current_date)
highs.append(high)
print(highs)
# 根据最高温度绘制图形。
plt.style.use('seaborn')
# 设置字体 ,如果不设置字体,则汉字无法显示
plt.rcParams["font.sans-serif"] = ["SimHei"]
# 该语句解决图像中的“-”负号的乱码问题
plt.rcParams["axes.unicode_minus"] = False
fig, ax = plt.subplots()
ax.plot(dates, highs, c='red')
ax.plot(dates, lows, c='blue')
ax.fill_between(dates, highs, lows, facecolor='blue', alpha=0.1)
# 设置图形的格式。
ax.set_title("重庆自从2018年年每日最高温度,和最低温度", fontsize=24)
ax.set_xlabel("日期", fontsize=16)
ax.set_ylabel("温度(C)", fontsize=16)
fig.autofmt_xdate()
ax.tick_params(axis='both', which='major', labelsize=16)
plt.show()
1.5 练习题
PRCP 降水量 为英寸。
转换公式为:1 英寸= 25.4 毫米。
sitka_prcp.py
import csv
import matplotlib.pyplot as plt
from datetime import datetime
filename = 'data/sitka_weather_2018_full.csv'
with open(filename) as file_object:
reader = csv.reader(file_object)
header_row = next(reader)
print(reader)
for index, column_header in enumerate(header_row):
print(index, column_header)
dates, prcps = [], []
for row in reader:
try:
prcp = float(row[5]) * 25.4
current_date = datetime.strptime(row[2], '%Y-%m-%d')
except ValueError:
print(f"Missing data for {current_date}")
else:
prcps.append(prcp)
dates.append(current_date)
print(prcps)
# 根据最高温度绘制图形。
plt.style.use('seaborn')
# 设置字体 ,如果不设置字体,则汉字无法显示
plt.rcParams["font.sans-serif"] = ["SimHei"]
# 该语句解决图像中的“-”负号的乱码问题
plt.rcParams["axes.unicode_minus"] = False
fig, ax = plt.subplots()
ax.plot(dates, prcps, c='red')
# 设置图形的格式。
ax.set_title("锡特卡从2018年年每日降水量", fontsize=24)
ax.set_xlabel("日期", fontsize=16)
ax.set_ylabel("降雨量(mm)", fontsize=16)
fig.autofmt_xdate()
ax.tick_params(axis='both', which='major', labelsize=16)
plt.show()
death_valley_prcp.py
import csv
import matplotlib.pyplot as plt
from datetime import datetime
filename = 'data/death_valley_2018_full.csv'
with open(filename) as file_object:
reader = csv.reader(file_object)
header_row = next(reader)
print(reader)
for index, column_header in enumerate(header_row):
print(index, column_header)
dates, prcps = [], []
for row in reader:
try:
prcp = float(row[3]) * 25.4
current_date = datetime.strptime(row[2], '%Y-%m-%d')
except ValueError:
print(f"Missing data for {current_date}")
else:
prcps.append(prcp)
dates.append(current_date)
print(prcps)
# 根据最高温度绘制图形。
plt.style.use('seaborn')
# 设置字体 ,如果不设置字体,则汉字无法显示
plt.rcParams["font.sans-serif"] = ["SimHei"]
# 该语句解决图像中的“-”负号的乱码问题
plt.rcParams["axes.unicode_minus"] = False
fig, ax = plt.subplots()
ax.plot(dates, prcps, c='red')
# 设置图形的格式。
ax.set_title("死亡谷从2018年年每日降水量", fontsize=24)
ax.set_xlabel("日期", fontsize=16)
ax.set_ylabel("降雨量(mm)", fontsize=16)
fig.autofmt_xdate()
ax.tick_params(axis='both', which='major', labelsize=16)
plt.show()
要设置 y 轴的取值范围,可使用 pyplot 函数 ylim() 要设置 x 轴的取值范围,可使用函数用函数xlim()。
import csv
from datetime import datetime
import matplotlib.pyplot as plt
def get_weather_date(filename, dates, highs, lows, date_index, high_index, low_index):
"""从数据文件中获取最高气温和最低气温。"""
with open(filename) as file_object:
reader = csv.reader(file_object)
header_row = next(reader)
for index, column_header in enumerate(header_row):
print(index, column_header)
for row in reader:
try:
low = (int(row[low_index]) - 31) // 1.8
high = (int(row[high_index]) - 31) // 1.8
current_date = datetime.strptime(row[date_index], '%Y-%m-%d')
except ValueError:
print(f"Missing data for {current_date}")
else:
lows.append(low)
dates.append(current_date)
highs.append(high)
def set_figure_env():
# 根据最高温度绘制图形。
plt.style.use('seaborn')
# 设置字体 ,如果不设置字体,则汉字无法显示
plt.rcParams["font.sans-serif"] = ["SimHei"]
# 该语句解决图像中的“-”负号的乱码问题
plt.rcParams["axes.unicode_minus"] = False
# 锡特卡
filename = 'data/sitka_weather_2018_full.csv'
# 获取最高气温和最低气温
dates, highs, lows = [], [], []
get_weather_date(filename, dates, highs, lows, date_index=2, high_index=8, low_index=9)
# 设置图形格式
set_figure_env()
# 绘制图形
fig, ax = plt.subplots()
ax.plot(dates, highs, c='red', alpha=0.55)
ax.plot(dates, lows, c='blue', alpha=0.55)
ax.fill_between(dates, highs, lows, facecolor='blue', alpha=0.25)
# 死亡谷
filename = 'data/death_valley_2018_full.csv'
# 获取最高气温和最低气温
dates, highs, lows = [], [], []
get_weather_date(filename, dates, highs, lows, date_index=2, high_index=6, low_index=7)
# 设置图形格式
set_figure_env()
# 绘制图形
ax.plot(dates, highs, c='red')
ax.plot(dates, lows, c='blue')
ax.fill_between(dates, highs, lows, facecolor='blue', alpha=0.25)
# 设置图形的格式。
ax.set_title("sitka气温,\n death_valry 气温", fontsize=24)
ax.set_xlabel("日期", fontsize=16)
ax.set_ylabel("温度(C)", fontsize=16)
fig.autofmt_xdate()
ax.tick_params(axis='both', which='major', labelsize=16)
# 设置y轴的取值范围
plt.ylim(-50, 50)
plt.show()
练习16-4:自动索引 本节以硬编码的方式指定了TMIN 和TMAX 列的索引。请根据文件头行确定这些列的索引,让程序同时适用于锡特卡和死亡谷。另外,请根据气象站的名称自动生成图表的标题
import csv
from datetime import datetime
import matplotlib.pyplot as plt
def get_weather_date(filename, dates, highs, lows, places):
"""从数据文件中获取最高气温和最低气温。"""
with open(filename) as file_object:
reader = csv.reader(file_object)
header_row = next(reader)
date_index = header_row.index('DATE')
high_index = header_row.index('TMAX')
low_index = header_row.index('TMIN')
name_index = header_row.index('NAME')
for index, column_header in enumerate(header_row):
print(index, column_header)
for row in reader:
try:
low = (int(row[low_index]) - 31) // 1.8
high = (int(row[high_index]) - 31) // 1.8
current_date = datetime.strptime(row[date_index], '%Y-%m-%d')
place_name = row[name_index]
except ValueError:
print(f"Missing data for {current_date}")
else:
lows.append(low)
dates.append(current_date)
highs.append(high)
places.append(place_name)
def set_figure_env():
# 根据最高温度绘制图形。
plt.style.use('seaborn')
# 设置字体 ,如果不设置字体,则汉字无法显示
plt.rcParams["font.sans-serif"] = ["SimHei"]
# 该语句解决图像中的“-”负号的乱码问题
plt.rcParams["axes.unicode_minus"] = False
# 锡特卡
filename = 'data/sitka_weather_2018_full.csv'
# 获取最高气温和最低气温
dates, highs, lows, places = [], [], [], []
get_weather_date(filename, dates, highs, lows, places)
# 设置图形格式
set_figure_env()
# 绘制图形
fig, ax = plt.subplots()
ax.plot(dates, highs, c='red', alpha=0.55)
ax.plot(dates, lows, c='blue', alpha=0.55)
ax.fill_between(dates, highs, lows, facecolor='blue', alpha=0.25)
# 死亡谷
filename = 'data/death_valley_2018_full.csv'
# 获取最高气温和最低气温
dates, highs, lows, places = [], [], [], []
get_weather_date(filename, dates, highs, lows, places)
# 设置图形格式
set_figure_env()
# 绘制图形
ax.plot(dates, highs, c='red')
ax.plot(dates, lows, c='blue')
ax.fill_between(dates, highs, lows, facecolor='blue', alpha=0.25)
# 设置图形的格式。
ax.set_title(f"当前显示的温度:{places[:1]}", fontsize=24)
ax.set_xlabel("日期", fontsize=16)
ax.set_ylabel("温度(C)", fontsize=16)
fig.autofmt_xdate()
ax.tick_params(axis='both', which='major', labelsize=16)
# 设置y轴的取值范围
plt.ylim(-50, 50)
plt.show()
2 JSON 地震数据
eq_explore_data.py
原生格式不好阅读,转换为可阅读格式。
import json
filename = 'data/eq_data_1_day_m1.json'
# 加载文件内容到all_eq_data ,all_eq_data 是一个字典。
with open(filename) as file_object:
all_eq_data = json.load(file_object)
# 打开不存在的文件,并将all_eq_data 内容写入到文件中。
# indent =4 是指缩进使用四个空格。
readable_file = 'data/readable_eq_data.json'
with open(readable_file, 'w') as file_read_object:
json.dump(all_eq_data, file_read_object, indent=4)
readable_eq_data.json
metadata 的片段:
- 指出了这个数据文件是什么时候生成的,以及能够在网上的什么地方找到。它还包含适合人类阅读的标题以及文件中记录了多少次地震:在过去的24小时内,发生了158次地震
- 这个geoJSON文件的结构适合存储基于位置的数据。数据存储在一个与键"features" 相关联的列表中这个文件包含的是地震数据,因此列表的每个元素都对应一次地震。
{
"type": "FeatureCollection",
"metadata": {
"generated": 1550361461000,
"url": "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/1.0_day.geojson",
"title": "USGS Magnitude 1.0+ Earthquakes, Past Day",
"status": 200,
"api": "1.7.0",
"count": 158
},
"features": [
键"properties" 关联到了与特定地震相关的大量信息(见❶)。我们关心的主要是与键"mag" 相关联的地震震级以及地震的标题,因为后者很好地概述了地震的震级和位置(见❷)
键"geometry" 指出了地震发生在什么地方(见❸),我们需要根据这项信息将地震在散点图上标出来。在与键"coordinates" 相关联的列表中,可找到地震发生位置的经度(见❹)和纬度(见❺)
readable_eq_data.json
{
"TYPE": "FEATURE",
"PROPERTIES": {
"MAG": 0.96,
"PLACE": "8KM NE OF AGUANGA, CA",
"TIME": 1550360775470,
"UPDATED": 1550360993593,
"TZ": -480,
"URL": "HTTPS://EARTHQUAKE.USGS.GOV/EARTHQUAKES/EVENTPAGE/CI37532978",
"DETAIL": "HTTPS://EARTHQUAKE.USGS.GOV/EARTHQUAKES/FEED/V1.0/DETAIL/CI37532978.GEOJSON",
"FELT": NULL,
"CDI": NULL,
"MMI": NULL,
"ALERT": NULL,
"STATUS": "AUTOMATIC",
"TSUNAMI": 0,
"SIG": 14,
"NET": "CI",
"CODE": "37532978",
"IDS": ",CI37532978,",
"SOURCES": ",CI,",
"TYPES": ",GEOSERVE,NEARBY-CITIES,ORIGIN,PHASE-DATA,",
"NST": 32,
"DMIN": 0.02648,
"RMS": 0.15,
"GAP": 37,
"MAGTYPE": "ML",
"TYPE": "EARTHQUAKE",
"TITLE": "M 1.0 - 8KM NE OF AGUANGA, CA"
},
"GEOMETRY": {
"TYPE": "POINT",
"COORDINATES": [
-116.7941667,
33.4863333,
3.22
]
},
"ID": "CI37532978"
},
2.1 绘制震级散点图
import json
import plotly.express as px
import pandas as pd
filename = 'data/eq_data_30_day_m1.json'
# 加载文件内容到all_eq_data ,all_eq_data 是一个字典。
with open(filename) as file_object:
all_eq_data = json.load(file_object)
# 打开不存在的文件,并将all_eq_data 内容写入到文件中。
# indent =4 是指缩进使用四个空格。
readable_file = 'data/readable_eq_data.json'
with open(readable_file, 'w') as file_read_object:
json.dump(all_eq_data, file_read_object, indent=4)
all_eq_dicts = all_eq_data['features']
# 提取震级和位置
mags, titles, lons, lats = [], [], [], []
for eq_dict in all_eq_dicts:
mag = eq_dict['properties']['mag']
title = eq_dict['properties']['title']
lon = eq_dict['geometry']['coordinates'][0]
lat = eq_dict['geometry']['coordinates'][1]
mags.append(mag)
titles.append(title)
lons.append(lon)
lats.append(lat)
data = pd.DataFrame(
data=zip(lons, lats, titles, mags), columns=["经度", "纬度", "位置", "震级"]
)
data.head()
print(mags[:2])
print(titles[:2])
print(lons[:2])
print(lats[:2])
fig = px.scatter_mapbox(data,
lon="经度",
lat="纬度",
hover_name="位置",
size="震级",
color="震级",
)
fig.update_layout(mapbox_style="open-street-map")
fig.update_layout(margin={"r": 0, "t": 0, "l": 0, "b": 0})
fig.write_html("global_earthquakes.html")
fig.show()

2.2 给散点图配色
show_color_scales.py
import plotly.express as px
for key in px.colors.named_colorscales():
print(key)
# 输出列表
aggrnyl
agsunset
blackbody
bluered
blues
blugrn
bluyl
brwnyl
bugn
bupu
burg
burgyl
cividis
darkmint
electric
emrld
gnbu
greens
greys
hot
inferno
jet
magenta
magma
mint
orrd
oranges
oryel
peach
pinkyl
plasma
plotly3
pubu
pubugn
purd
purp
purples
purpor
rainbow
rdbu
rdpu
redor
reds
sunset
sunsetdark
teal
tealgrn
turbo
viridis
ylgn
ylgnbu
ylorbr
ylorrd
algae
amp
deep
dense
gray
haline
ice
matter
solar
speed
tempo
thermal
turbid
armyrose
brbg
earth
fall
geyser
prgn
piyg
picnic
portland
puor
rdgy
rdylbu
rdylgn
spectral
tealrose
temps
tropic
balance
curl
delta
oxy
edge
hsv
icefire
phase
twilight
mrybm
mygbm
2.2.1 使用渐变色方式
fig = px.scatter_mapbox(data,
title="全球地震散点图",
lon="经度",
lat="纬度",
hover_name="位置",
size="震级",
size_max=10,
color="震级",
color_continuous_scale=px.colors.diverging.Armyrose,
)
px.colors.diverging.RdYlGn[::-1]
渐变色方案
| 选项 | 说明 |
|---|---|
| px.colors.diverging | 两种颜色表示连续变量的配色方案。 |
| px.colors.sequential | 离散变量配色方案。表现为连续的色条 |
| px.colors.qualitative | 离散变量配色方案。 |
px.colors.diverging

px.colors.sequential

px.colors.qualitative

2.3 练习题
import json
import plotly.express as px
import pandas as pd
filename = 'data/eq_data_30_day_m1.json'
# 加载文件内容到all_eq_data ,all_eq_data 是一个字典。
with open(filename) as file_object:
all_eq_data = json.load(file_object)
# 打开不存在的文件,并将all_eq_data 内容写入到文件中。
# indent =4 是指缩进使用四个空格。
readable_file = 'data/readable_eq_data.json'
with open(readable_file, 'w') as file_read_object:
json.dump(all_eq_data, file_read_object, indent=4)
# 提取标题
sum_title = all_eq_data['metadata']['title']
# 提取震级和位置
all_eq_dicts = all_eq_data['features']
mags, titles, lons, lats = [], [], [], []
for eq_dict in all_eq_dicts:
mag = eq_dict['properties']['mag']
title = eq_dict['properties']['title']
lon = eq_dict['geometry']['coordinates'][0]
lat = eq_dict['geometry']['coordinates'][1]
mags.append(mag)
titles.append(title)
lons.append(lon)
lats.append(lat)
data = pd.DataFrame(
data=zip(lons, lats, titles, mags), columns=["经度", "纬度", "位置", "震级"]
)
data.head()
print(mags[:2])
print(titles[:2])
print(lons[:2])
print(lats[:2])
fig = px.scatter_mapbox(data,
lon="经度",
lat="纬度",
hover_name="位置",
size="震级",
size_max=10,
color="震级",
color_continuous_scale=px.colors.diverging.balance,
)
fig.update_layout(mapbox_style="open-street-map")
fig.update_layout(title_text=f"{sum_title}")
fig.write_html("global_earthquakes.html")
fig.show()
如果在使用其他地震数据 1小时,1天,7天,30天的地震数据时,由于mag 震级可能为负值。所以size 不支持负数。所以需要注释代码:
# size="震级",